<script setup>
import draggable from "vuedraggable";
import { Loading, Plus, ZoomIn, Delete } from '@element-plus/icons-vue'

const emits = defineEmits(['change'])
const props = defineProps({
    list: { type: Array, default: [] },//列表图片数据
    maxCount: { type: Number, default: 10 }//最多允许上传的图片数量
})

const status = reactive({
    showPreview: false,//显示图片预览
    showProgress: false,//显示上传中
})
const data = reactive({
    list: ['', ...props.list],//第一列空为图片按钮占用位
    preview: {
        index: 0,
        list: []
    }
})
const uploadInput = ref()//上传图片控件

onMounted(() => {
    //如果props数据通过ajax请求,数据会在页面执行完了后再传入
    //这里加入一个监听确保ajax数据传入,主页重置数据时也需要监听并修改
    watch(() => props.list, () => {
        if (!Array.isArray(props.list)) {
            data.list = ['']
        } else {
            data.list = ['', ...props.list]
        }
    })
})

//第一个位置为添加图片按钮,不允许拖动到第一个位置
const draggableMove = (item) => {
    if ((data.list.length - 1) >= props.maxCount) {
        return true
    } else if (item.draggedContext.futureIndex == 0) {
        return false
    }
}
//排序结束时
const draggableEnd = (item) => {
    emits('change', data.list.slice(1))
}
//删除图片时
const remove = (index) => {
    data.list.splice(index, 1)
    emits('change', data.list.slice(1))
}
//选择图片时自动上传
const uploadChange = (event) => {
    const files = Array.from(event.target.files);
    //判断允许上传的最大条数
    if (props.maxCount - (data.list.length - 1) - files.length < 0) {
        const residue = (props.maxCount - (data.list.length - 1))
        let residueMessage = '最多还可选择' + residue + '张'
        if (residue <= 0) {
            residueMessage = '不可继续选择,如需更换请删除需要更换的图片'
        }
        sys.tip({
            message: residueMessage + '(最多允许上传' + props.maxCount + '张图片,当前已上传' + (data.list.length - 1) + '张已选' + files.length + '张)',
            type: 'warning',
            grouping: true
        })
        return false
    }
    //显示上传中
    let endCount = 0
    const allCount = files.length
    status.showProgress = true
    const showProgressInterval = setInterval(() => {
        if (endCount == allCount) {
            clearInterval(showProgressInterval)
            status.showProgress = false
        }
    }, 100)
    //开始一个个上传
    for (const i in files) {
        const item = files[i]
        //判断图片大小
        if (item.size > config.upload.imageMaxSize) {
            const fileSizeTxt = (item.size / 1024 / 1024).toFixed(2) * 100 / 100 + 'M'
            const maxSizeTxt = (config.upload.imageMaxSize / 1024 / 1024).toFixed(2) * 100 / 100 + 'M'
            sys.tip({
                message: '"' + item.name + '" 大小为' + fileSizeTxt + ', 超过了' + maxSizeTxt + '的上传限制。',
                type: 'warning',
                grouping: true
            })
            endCount++
            return true
        }
        //开始上传
        const formData = new FormData();
        formData.append('image', item);
        axios.post('/uploads/image', formData).then(response => {
            endCount++
            if (response.status == 1) {
                data.list.push(response.data)
                emits('change', data.list.slice(1))
            } else {
                sys.tip(response)
            }
        }).catch(error => {
            endCount++
        })
    }
}
//查看图片
const preview = (index) => {
    const list = []
    for (const i in data.list) {
        const item = data.list[i]
        if (i != 0) list.push(item.url)
    }
    data.preview.list = list;
    data.preview.index = index - 1
    status.showPreview = true;
}
</script>

<template>
    <div>
        <input ref="uploadInput" type="file" @click="() => { uploadInput.value = null }" @change="uploadChange"
            accept="image/*" :multiple="props.maxCount > 1" style="display: none;" />
        <draggable class="upload" v-model="data.list" item-key="index" handle=".mover" @end="draggableEnd"
            :move="draggableMove">
            <template #item="{ index, element }">
                <div class="button-box mr10 mb10" v-show="props.maxCount > (data.list.length - 1)" v-if="index == 0"
                    @click="() => { uploadInput.click() }">
                    <el-icon v-if="status.showProgress" class="is-loading">
                        <Loading />
                    </el-icon>
                    <el-icon v-else>
                        <Plus />
                    </el-icon>
                </div>
                <div v-else class="image-box mover mr10 mb10">
                    <el-image :src="element.url" fit="contain" style="width:100%;height: 100%;" />
                    <div class="image-shadow-box">
                        <div class="image-edit flex-c">
                            <el-icon @click="preview(index)" class="mr10">
                                <ZoomIn />
                            </el-icon>
                            <el-icon @click="remove(index)">
                                <Delete />
                            </el-icon>
                        </div>
                    </div>
                </div>
            </template>
        </draggable>
        <div v-if="status.showPreview && data.preview.list.length > 1"
            class="el-image-viewer__btn el-image-viewer__actions preview-count" style="z-index: 12;">{{
                data.preview.index + 1
            }}/{{ data.preview.list.length }}</div>
        <el-image-viewer :z-index="11" v-if="status.showPreview" @close="() => { status.showPreview = false }"
            :url-list="data.preview.list" :initial-index="data.preview.index"
            @switch="(index) => { data.preview.index = index }" />
    </div>
</template>

<style scoped lang="scss">
.upload {

    .button-box,
    .image-box {
        &:hover {
            border-color: var(--el-color-primary);
            color: var(--el-color-primary);
        }

        background-color: var(--el-fill-color-lighter);
        border: 1px dashed var(--el-border-color-darker);
        border-radius: 6px;
        box-sizing: border-box;
        width: 148px;
        height: 148px;
        cursor: pointer;
        vertical-align: top;
        display: inline-flex;
        justify-content: center;
        align-items: center;
        position: relative;

        .el-icon {
            font-size: 25px;
            color: #8c939d;
        }
    }

    .image-shadow-box {
        position: absolute;
        width: 100%;
        height: 100%;
        cursor: move;

        .image-edit {
            &:hover {
                opacity: 1;
            }

            transition: opacity var(--el-transition-duration);
            background: var(--el-overlay-color-lighter);
            border-radius: 6px;
            opacity: 0;
            position: absolute;
            font-size: 20px;
            width: 100%;
            height: 100%;

            .el-icon {
                font-size: 20px;
                color: #fff;
                cursor: pointer;
            }
        }
    }
}

.preview-count {
    position: fixed;
    top: 30px;
    color: #fff;
    font-weight: bold;
    width: auto;
    padding: 0px 40px;
}
</style>
